package com.example.chamberlainserver.aspect;

import com.example.chamberlainserver.Service.TokenValidationService;
import com.example.chamberlainserver.Vo.Response.ApiResponse;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * Token验证切面
 * 拦截所有Controller方法，验证当前token是否有效
 */
@Aspect
@Component
public class TokenValidationAspect {

    @Autowired
    private TokenValidationService tokenValidationService;

    /**
     * 定义切点，拦截所有Controller方法
     * 排除登录、注册和登出接口
     */
    @Pointcut("execution(* com.example.chamberlainserver.controller.*.*(..)) && " +
            "!execution(* com.example.chamberlainserver.controller.AuthController.*(..))")
    public void controllerMethods() {
    }

    /**
     * 环绕通知，验证token是否有效
     *
     * @param joinPoint 连接点
     * @return 方法执行结果或错误响应
     * @throws Throwable 异常
     */
    @Around("controllerMethods()")
    public Object validateToken(ProceedingJoinPoint joinPoint) throws Throwable {
        // 获取当前请求
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes == null) {
            // 如果无法获取请求属性，直接执行原方法
            return joinPoint.proceed();
        }

        HttpServletRequest request = attributes.getRequest();
        String requestURI = request.getRequestURI();
        
        // 获取请求头中的token
        String requestTokenHeader = request.getHeader("Authorization");
        String jwtToken = tokenValidationService.extractTokenFromHeader(requestTokenHeader);
        
        if (jwtToken == null) {
            System.out.println("TokenValidationAspect: 请求 " + requestURI + " 缺少有效的Authorization头");
            return ResponseEntity.ok(ApiResponse.error(401, "未认证，请重新登录"));
        }
        
        // 检查token是否过期
        if (!tokenValidationService.isTokenNotExpired(jwtToken)) {
            System.out.println("TokenValidationAspect: 请求 " + requestURI + " token已过期");
            return ResponseEntity.ok(ApiResponse.error(401, "token已过期，请重新登录"));
        }
        
        // 获取当前认证信息
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        
        // 如果认证信息为空，返回未认证错误
        if (authentication == null || !authentication.isAuthenticated()) {
            System.out.println("TokenValidationAspect: 请求 " + requestURI + " 未认证");
            return ResponseEntity.ok(ApiResponse.error(401, "未认证，请重新登录"));
        }
        
        // 验证token是否有效
        if (!tokenValidationService.validateToken(jwtToken, authentication)) {
            System.out.println("TokenValidationAspect: 请求 " + requestURI + " token无效");
            return ResponseEntity.ok(ApiResponse.error(401, "token无效，请重新登录"));
        }
        
        // token有效，执行原方法
        System.out.println("TokenValidationAspect: 请求 " + requestURI + " token有效");
        return joinPoint.proceed();
    }
}